﻿#ifndef UTILS_H
#define UTILS_H

#include <string>
#include <cstdarg>

namespace utils_rsa{

enum KeyType{
    RSA_PUBKEY_TYPE,
    RSA_PRIKEY_TYPE,
    OTHER
};

void GenerateRsaKeyCstr(char* &prikey_cstr, char* &pubkey_cstr, int key_len, size_t& pubkey_len, size_t& prikey_len);
void GenerateRsaKey(std::string &prikey, std::string &pubkey, int key_len);

bool RsaEncryptUsingPubkey(const std::string pubkey, const std::string clear_text, std::string &encrypted_text);
bool RsaDecryptUsingPrikey(const std::string prikey, const std::string encrypted_text, std::string &clear_text);

bool RsaEncryptUsingPrikey(const std::string prikey, const std::string clear_text, std::string &encrypted_text);
bool RsaDecryptUsingPubkey(const std::string pubkey, const std::string encrypted_text, std::string &clear_text);

std::string StrToHexStr(std::string str);

KeyType CheckKeyType(std::string probale_key);
}

namespace utils_sock{
#if WIN32
typedef unsigned int sock_fd_t;
#else
typedef int sock_fd_t;
#endif

sock_fd_t CreateClientSockFd(std::string ip, unsigned short port);
bool SendMsg(sock_fd_t sock_fd, std::string msg);
bool SendRsaPubkeyEncryptedMsg(sock_fd_t sock_fd, std::string pubkey, std::string clear_msg);
bool CheckIpAddrFormat(std::string ip_addr);
sock_fd_t CreateListenSockFd(unsigned short port);
bool CheckFdValid(sock_fd_t fd);

const int SOCK_TYPE_CLIENT = 0;
const int SOCK_TYPE_SERVER = 1;

const int SOCK_STATUS_NOT_CREATED           = -1;
const int SOCK_STATUS_NOT_CONNECTED         = 0;
const int SOCK_STATUS_CONNECTED             = 1;
const int SOCK_STATUS_DISCONNECTED          = 2;
const int SOCK_STATUS_FAILED_TO_CONNECTED   = 3;
const int SOCK_STATUS_LISTENING             = 4;
const int SOCK_STATUS_FAILED_TO_LISTEN      = 5;
const int SOCK_STATUS_CONNECTED_TO_CLIENT   = 6;

class TcpSocketWrapper{
public:
    explicit TcpSocketWrapper(int type, unsigned int local_port, const char* remote_ip = "", unsigned int remote_port = 0);
    void Connect();
    void Listen();
    int CheckStatus();
    void Disconnect();
    void Send(const char* buffer);
    ~TcpSocketWrapper();
private:
    sock_fd_t fd;
    int type;
    unsigned int local_port;
    unsigned int remote_port;
    std::string remote_ip;
    int status;
    char* recv_buffer;
#if WIN32
    void SetupWSA();
    void ShutdownWSA();
#endif
};

}

namespace utils_log{

enum ErrCode{
    OUT_OF_RANGE,
    FORMAT_ERROR
};

enum OpCode{
    CLICK_PUSH_BUTTON
};

void QdebugWithLog(std::string new_content, std::string &log_str);
void UserOpLog(int op_code, std::string &log_str, ...);
void SystemInfoLog(std::string info_str, std::string &log_str);
void SystemErrLog(int err_code, std::string &log_str, ...);
}

#endif
